#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 初始化 UDP 套接字
    udpSocket = new QUdpSocket(this);
    udpSocket->bind(QHostAddress::Any, 12345);
    connect(udpSocket, &QUdpSocket::readyRead, this, &MainWindow::readPendingDatagrams);

    // 初始化定时器
    pingTimer = new QTimer(this);
    connect(pingTimer, &QTimer::timeout, this, &MainWindow::on_pingTimer_timeout);
    registrationTimer = new QTimer(this);
    connect(registrationTimer, &QTimer::timeout, this, &MainWindow::checkRegistrationTimeout);
    sendTimer = new QTimer(this);
    connect(sendTimer, &QTimer::timeout, this, &MainWindow::checkSendTimeout);

    // 初始化 Ping 进程
    pingProcess = new QProcess(this);
    connect(pingProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
            this, &MainWindow::on_pingProcess_finished);

    // 获取 UI 元素指针
    progressBar = ui->progressBar;
    registrationFailureLabel = ui->registrationFailureLabel;
    sendFailureLabel = ui->sendFailureLabel;
    ipPart1Edit = ui->ipPart1Edit;
    ipPart2Edit = ui->ipPart2Edit;
    ipPart3Edit = ui->ipPart3Edit;
    ipPart4Edit = ui->ipPart4Edit;
    portLineEdit = ui->portLineEdit;
    startConnectButton = ui->startConnectButton;
    startRegistrationButton = ui->startRegistrationButton;
    sendButton = ui->sendButton;
    receiveTextEdit = ui->receiveTextEdit;
    sendTextEdit = ui->sendTextEdit;
    asciiRadioButton = ui->asciiRadioButton;
    binaryRadioButton = ui->binaryRadioButton;

    // 初始化计数器和标志
    registrationFailureCount = 0;
    sendFailureCount = 0;
    registrationInProgress = false;
    sendInProgress = false;
}

MainWindow::~MainWindow()
{
    delete ui;
}

QString MainWindow::getFullIP()
{
    return ipPart1Edit->text() + "." + ipPart2Edit->text() + "." + ipPart3Edit->text() + "." + ipPart4Edit->text();
}

void MainWindow::on_startConnectButton_clicked()
{
    QString ip = getFullIP();
    if (!ip.isEmpty()) {
        pingTimer->start(1000);
        on_pingTimer_timeout();
    }
}

void MainWindow::on_pingTimer_timeout()
{
    QString ip = getFullIP();
    if (!ip.isEmpty()) {
        QString command = "ping -c 1 " + ip;
        pingProcess->start(command);
    }
}

void MainWindow::on_startRegistrationButton_clicked()
{
    registrationInProgress = true;
    progressBar->setValue(0);
    progressBar->setRange(0, 20000);
    registrationTimer->start(100);
    startRegistrationButton->setEnabled(false);
}

void MainWindow::on_sendButton_clicked()
{
    if (!registrationInProgress && !sendInProgress) {
        sendInProgress = true;
        QString message = sendTextEdit->toPlainText();
        if (!message.isEmpty()) {
            QDateTime sendTime = QDateTime::currentDateTime();
            QString sendTimeStr = sendTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
            QString displayMsg = "发送时间: " + sendTimeStr + ", 发送内容: " + message;
            receiveTextEdit->append(displayMsg);

            QByteArray datagram;
            if (asciiRadioButton->isChecked()) {
                datagram = message.toUtf8();
            } else if (binaryRadioButton->isChecked()) {
                datagram = QByteArray::fromHex(message.toUtf8());
            }

            udpSocket->writeDatagram(datagram, QHostAddress(getFullIP()), portLineEdit->text().toInt());
            sendTimer->start(5000);
        }
    }
}

void MainWindow::readPendingDatagrams()
{
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;

        udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        QDateTime receiveTime = QDateTime::currentDateTime();
        QString receiveTimeStr = receiveTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
        QString message = QString::fromUtf8(datagram);
        QString displayMsg = "接收时间: " + receiveTimeStr + ", 接收内容: " + message;
        receiveTextEdit->append(displayMsg);

        if (registrationInProgress) {
            if (message.toUpper() == "CONNECT OK") {
                registrationTimer->stop();
                registrationInProgress = false;
                startRegistrationButton->setEnabled(true);
                receiveTextEdit->append("注网成功");
                on_sendButton_clicked();
            }
        } else if (sendInProgress) {
            if (message.toUpper() == "ERROR") {
                sendFailureCount++;
                sendFailureLabel->setText("发送失败次数: " + QString::number(sendFailureCount));
                sendInProgress = false;
                sendTimer->stop();
                receiveTextEdit->append("发送失败: 收到 ERROR");
                on_startRegistrationButton_clicked();
            } else {
                sendInProgress = false;
                sendTimer->stop();
                receiveTextEdit->append("发送成功");
                on_sendButton_clicked();
            }
        }
    }
}

void MainWindow::checkRegistrationTimeout()
{
    if (registrationInProgress) {
        int elapsed = progressBar->value() + 100;
        progressBar->setValue(elapsed);
        if (elapsed >= 20000) {
            registrationTimer->stop();
            registrationFailureCount++;
            registrationFailureLabel->setText("注网失败次数: " + QString::number(registrationFailureCount));
            receiveTextEdit->append("注网失败: 超时，重新注网");
            on_startRegistrationButton_clicked();
        }
    }
}

void MainWindow::checkSendTimeout()
{
    if (sendInProgress) {
        sendFailureCount++;
        sendFailureLabel->setText("发送失败次数: " + QString::number(sendFailureCount));
        sendInProgress = false;
        sendTimer->stop();
        receiveTextEdit->append("发送失败: 超时，重新注网");
        on_startRegistrationButton_clicked();
    }
}

void MainWindow::on_pingProcess_finished(int exitCode, QProcess::ExitStatus exitStatus)
{
    QString ip = getFullIP();
    if (exitStatus == QProcess::NormalExit && exitCode == 0) {
        ui->pingResultLabel->setText("ping " + ip + " 成功");
    } else {
        ui->pingResultLabel->setText("ping " + ip + " 失败");
    }
}
